/*              Copyright(c) 2008 Dave Sexton              *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.XPath;
using System.ComponentModel;
using System.ComponentModel.Design;

namespace DaveSexton.Sandcastle
{
	partial class ResolveExternalLinksComponentConfiguration
	{
		#region Public Properties
		/// <summary>
		/// Gets an <see cref="XPathNavigator"/> that can be used to read and write
		/// the component's XML configuration section.
		/// </summary>
		[Browsable(false)]
		public XPathNavigator Navigator
		{
			get
			{
				return __config;
			}
		}

		/// <summary>
		/// Gets or sets the value of the component's <c>id</c> attribute in the Build Assembler 
		/// configuration file.
		/// </summary>
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public string ComponentId
		{
			get
			{
				return ReadAttribute("id") ?? "";
			}
			set
			{
				WriteAttribute("id", value);
			}
		}

		/// <summary>
		/// Gets or sets the raw XML data for the component.
		/// </summary>
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public string RawData
		{
			get
			{
				return __config.InnerXml;
			}
			set
			{
				__config.InnerXml = value;
			}
		}

		/// <summary>
		/// Gets an instance of the <see cref="ResolveExternalLinksComponentHost"/> class that provides a facade
		/// for interacting with the host, if one exists.
		/// </summary>
		[Browsable(false)]
		public ResolveExternalLinksComponentHost Host
		{
			get
			{
				return __host;
			}
		}

		[Browsable(false)]
		public object ComponentValue
		{
			get
			{
				return __componentValue;
			}
		}
		#endregion

		#region Private / Protected
		public static readonly string DefaultDisplayName = GetDefaultDisplayName();

		private readonly ResolveExternalLinksComponentHost __host;
		private readonly XPathNavigator __config;
		private readonly object __componentValue;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="ResolveExternalLinksComponentConfiguration" /> class.
		/// </summary>
		private ResolveExternalLinksComponentConfiguration(ResolveExternalLinksComponentHost host, IXPathNavigable config)
		{
			if (config == null)
				throw new InvalidOperationException(
					"The host application failed to provide configuration data for " + DefaultDisplayName);

			this.__host = host;
			this.__componentValue = config;
			this.__config = config.CreateNavigator();

			Initialize();
		}
		#endregion

		#region Methods
		/// <summary>
		/// Creates a strong-typed wrapper around the specified XML <paramref name="configuration"/>
		/// for use without a host API, such as during builds.
		/// </summary>
		public static ResolveExternalLinksComponentConfiguration GetConfiguration(IXPathNavigable configuration)
		{
			return new ResolveExternalLinksComponentConfiguration(null, configuration);
		}

		/// <summary>
		/// Creates a strong-typed wrapper around the specified XML <paramref name="configuration"/>
		/// for use with a compatible host API, if one exists.
		/// </summary>
		public static ResolveExternalLinksComponentConfiguration GetConfiguration(IServiceProvider provider, IXPathNavigable configuration)
		{
			return new ResolveExternalLinksComponentConfiguration(ResolveExternalLinksComponentHost.GetHost(provider), configuration);
		}

		private static string GetDefaultDisplayName()
		{
			string displayName = typeof(ResolveExternalLinksComponent).FullName;

			AttributeCollection attributes = TypeDescriptor.GetAttributes(typeof(ResolveExternalLinksComponent));

			if (attributes != null)
			{
				DisplayNameAttribute name = (DisplayNameAttribute) attributes[typeof(DisplayNameAttribute)];

				if (name != null && !name.IsDefaultAttribute())
					displayName = name.DisplayName;
			}

			return displayName;
		}

		/// <summary>
		/// Gets the display name for use in the component's editor.
		/// </summary>
		public static string GetDisplayName(ITypeDescriptorContext context, IServiceProvider provider, ResolveExternalLinksComponentConfiguration configuration)
		{
			return DefaultDisplayName;
		}

		/// <summary>
		/// Gets the value for the component when it's represented as a property in a propety grid.
		/// </summary>
		public static string GetDisplayValue(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, IXPathNavigable configuration)
		{
			return string.Empty;
		}

		/// <summary>
		/// Returns the value of the attribute with the specified <paramref name="name"/> on the 
		/// component's element in the Build Assembler configuration file in which the component 
		/// is defined, or <see langword="null"/> if the attribute does not exist.
		/// </summary>
		public string ReadAttribute(string name)
		{
			XPathNavigator navigator = __config.Clone();

			if (navigator.MoveToAttribute(name, ""))
				return navigator.Value;
			else
				return null;
		}

		/// <summary>
		/// Writes the <paramref name="value"/> of the attribute with the specified <paramref name="name"/> 
		/// on the component's element in the Build Assembler configuration file in which the 
		/// component is defined.
		/// </summary>
		/// <remarks>
		/// Specify <see langword="null"/> for the <paramref name="value"/> argument and the 
		/// attribute will be removed from the configuration.
		/// </remarks>
		public void WriteAttribute(string name, string value)
		{
			XPathNavigator navigator = __config.Clone();

			if (navigator.MoveToAttribute(name, ""))
			{
				if (value == null)
					navigator.DeleteSelf();
				else
					navigator.SetValue(value);
			}
			else if (value != null)
				navigator.CreateAttribute(null, name, null, value);
		}
		#endregion
	}
}
